-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--[[

]]--
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
local assets =
{
    Asset("ANIM", "anim/loramia_building_guardian_creation.zip"),
}
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--- 参数
    local HEAL_POWER_COST_PER_SECOND = 1        --- 治疗的时候每秒消耗的电力
    local HEAL_VALUE_UP_PER_SECOND = 10         --- 每秒回复的生命值
    local COMBAT_SEARCH_RADIUS = 4*8            --- 搜索敌人的半径
    local COMBAT_DAMAGE = 200                   --- 攻击造成的伤害
    local COMBAT_PERIODIC_TIME = 3              --- 攻击间隔
    local COMBAT_POWER_COST_PER_HIT = 2         --- 每次攻击消耗的电力
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--- snow
    local function snow_init(inst)
        if TheWorld.state.issnowcovered then
            -- inst.AnimState:Show("SNOW")
            inst.AnimState:ShowSymbol("snow")
        else
            -- inst.AnimState:Hide("SNOW")
            inst.AnimState:HideSymbol("snow")
        end    
    end
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--- 电器节点安装
    local function device_com_install(inst)
        inst:ListenForEvent("Loramia_OnEntityReplicated.loramia_com_power_device",function(inst,replica_com)
            replica_com:SetIndicatorColor(0/255,255/255,0/255)
        end)
        if not TheWorld.ismastersim then
            return
        end
        inst:AddComponent("loramia_com_power_device")
        inst.components.loramia_com_power_device:SetIndicator(true)
        inst.components.loramia_com_power_device:SetIndicatorRadius(COMBAT_SEARCH_RADIUS)
    end
    local function take_power_succeed(inst,value)
        return inst.components.loramia_com_power_device:IsGotPowerSucceed(value)
    end
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--- workable2
    local function custom_workable_install(inst)
        inst:ListenForEvent("Loramia_OnEntityReplicated.loramia_com_workable",function(inst,replica_com)
            replica_com:SetTestFn(function(inst,doer,right_click)
                if right_click and doer:HasTag("loramia") then
                    if doer.replica.loramia_com_talent_tree:IsUnlocked("evolution_defense") or TUNING.LORAMIA_DEBUGGING_MODE then
                        return true
                    end
                end
            end)
            replica_com:SetText("loramia_building_guardian_creation",STRINGS.ACTIONS.WRAPBUNDLE)
        end)
        if not TheWorld.ismastersim then
            return
        end
        inst:AddComponent("loramia_com_workable")
        inst.components.loramia_com_workable:SetOnWorkFn(function(inst,doer)
            local x,y,z = inst.Transform:GetWorldPosition()
            local item = SpawnPrefab("loramia_building_guardian_creation_kit")
            item.Transform:SetPosition(x,y,z)
            inst:Remove()
            return true
        end)
    end
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--- workable
    local function OnFinishCallback(inst,worker)
        inst.components.lootdropper:SpawnLootPrefab("redgem")
        inst.components.lootdropper:SpawnLootPrefab("yellowgem")
        local fx = SpawnPrefab("collapse_small")
        fx.Transform:SetPosition(inst.Transform:GetWorldPosition())
        inst:Remove()
    end
    local function workable_install(inst)
        inst:AddComponent("workable")
        inst.components.workable:SetWorkAction(ACTIONS.DIG)
        inst.components.workable:SetWorkLeft(1)
        -- inst.components.workable:SetOnWorkCallback(onhit)
        inst.components.workable:SetOnFinishCallback(OnFinishCallback)

        --- 除非玩家主动敲打，否则不会掉落
        local old_WorkedBy = inst.components.workable.WorkedBy
        inst.components.workable.WorkedBy = function(self,worker, numworks,...)
            if worker and worker:HasTag("player") then
                return old_WorkedBy(self,worker, numworks,...)
            end
        end
        local old_WorkedBy_Internal = inst.components.workable.WorkedBy_Internal
        inst.components.workable.WorkedBy_Internal = function(self,worker, numworks,...)
            if worker and worker:HasTag("player") then
                return old_WorkedBy_Internal(self,worker, numworks,...)
            end
        end
    end
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--- 
    local ignore_action = {
        [ACTIONS.CHOP] = true,
        [ACTIONS.HAMMER] = true,
        [ACTIONS.MINE] = true,
        [ACTIONS.DIG] = true,
    }
    local workable_destroy_checker_fn = function(target)        
        -- print("workable_destroy_checker_fn",target)
        if target.components.workable and ignore_action[target.components.workable:GetWorkAction()] then
            return false
        end
        if target:HasOneOfTags({"structure","engineering","wall","plant"}) then
            return false
        end
        return true
    end
    local musthavetags = {"_combat"}
    local canthavetags = {"companion","player", "brightmare", "playerghost", "INLIMBO","flight","chester","hutch","DECOR", "FX","structure","wall","engineering","eyeturret"}
    local musthaveoneoftags = nil
    local function GetTarget(inst)
        local x,y,z = inst.Transform:GetWorldPosition()
        local targets = {}
        local ents = TheSim:FindEntities(x,y,z,COMBAT_SEARCH_RADIUS or 20,musthavetags,canthavetags,musthaveoneoftags)
        for k, temp in pairs(ents) do
            if temp and temp.components.combat and temp.components.health and not temp.components.health:IsDead() and workable_destroy_checker_fn(temp) then
                -- ret_targets_with_ditance[temp] = temp:GetDistanceSqToPoint(x,y,z)
                table.insert(targets,temp)
            end
        end

        if #targets == 0 then
            return nil
        end
        -----------------------------------------------------------------
        --- 不攻击没敌意的目标
            local ret_targets_with_ditance = {}
            for k,temp in pairs(targets) do
                local temp_target = temp.components.combat.target
                -- and temp_target:HasOneOfTags({"player","companion","structure","wall"})
                if temp_target then
                    ret_targets_with_ditance[temp] = temp:GetDistanceSqToPoint(x,y,z)
                end
            end
        -----------------------------------------------------------------
        --- 优先攻击对玩家有敌意的单位
            local nearest_target = nil
            local nearest_distance = nil
            for k, v in pairs(ret_targets_with_ditance) do
                if nearest_target == nil or nearest_distance > v then
                    nearest_target = k
                    nearest_distance = v
                end
            end
        -----------------------------------------------------------------
        return nearest_target
    end
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--- combat and health    
    local function laser_create_for_target(inst,target)
        ----------------------------------------------
        --[[

            在inst 和 target 的连线上，
            起始点：inst 和 target 的中点
            末尾点：攻击距离的最远点

            ]]--
        ----------------------------------------------
        --- fx
            local fx = inst:SpawnChild("loramia_building_guardian_creation_fx")
            fx.entity:SetParent(inst.entity)
			fx.entity:AddFollower()
			fx.Follower:FollowSymbol(inst.GUID,"ring",0,0,0)
            local num = inst.fx_flag and 1 or 2
            fx.AnimState:PlayAnimation("hit_fx_"..num)
            inst.fx_flag = not inst.fx_flag
            fx:ListenForEvent("animover",fx.Remove)
        ----------------------------------------------
        ---
            local x,y,z = inst.Transform:GetWorldPosition()
            local tx,ty,tz = target.Transform:GetWorldPosition()            
        ----------------------------------------------
        --- 起始点
            local start_pt = Vector3((x+tx)/2,0,(z+tz)/2)
        ----------------------------------------------
        --- 归一化
            local dir = Vector3(tx-x,0,tz-z):GetNormalized()
        ----------------------------------------------
        --- 末尾点
            local end_pt = start_pt + dir * COMBAT_SEARCH_RADIUS
        ----------------------------------------------
        ---
            SpawnPrefab("loramia_spell_line_laser_beam"):PushEvent("Set",{
                start_pt = start_pt,
                end_pt = end_pt,
                colour = {0,255,0},
                delta_length = 1,
                delay_frame = 0.4,
                -- onhit_delay_frame = 10,
                onhitfn = function(x,y,z)
                    local ents = TheSim:FindEntities(x, 0, z, 1.2, musthavetags, canthavetags, musthaveoneoftags)
                    for k, temp in pairs(ents) do
                        if temp and temp.components.combat and temp.components.health and not temp.components.health:IsDead() and workable_destroy_checker_fn(temp) then
                            -- temp.components.combat:GetAttacked(inst,COMBAT_DAMAGE_PER_HIT)
                            temp.components.combat:GetAttacked(inst,COMBAT_DAMAGE or 200)
                        end
                    end
                end,
                sound = "loramia_sound/loramia_sound/guardian_creation_attack"
            })
        ----------------------------------------------
    end
    local function combat_install(inst)
        inst:AddComponent("health")
        inst.components.health:SetMaxHealth(3000)
        --- 连接状态下每秒+10
        inst:DoPeriodicTask(1,function()
            if inst.components.health:GetPercent() < 1 and take_power_succeed(inst,HEAL_POWER_COST_PER_SECOND) then
                inst.components.health:DoDelta(HEAL_VALUE_UP_PER_SECOND or 10,true)
            end
        end)

        inst:AddComponent("combat")

        inst:DoPeriodicTask(TUNING.LORAMIA_DEBUGGING_MODE and 1 or COMBAT_PERIODIC_TIME or 5,function()
            local target = GetTarget(inst)
            if target and take_power_succeed(inst,COMBAT_POWER_COST_PER_HIT) then
                laser_create_for_target(inst,target)
            end
        end)
    end
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--- core_light
    local function CreateCoreLight(inst)
        local fx = inst:SpawnChild("loramia_building_guardian_creation_fx")
        fx.entity:SetParent(inst.entity)
        fx.entity:AddFollower()
        fx.Follower:FollowSymbol(inst.GUID,"icon",0,0,0)
        fx.AnimState:PlayAnimation("fx",true)
        fx:Hide()
        inst:DoPeriodicTask(1,function()
            if inst.components.loramia_com_power_device:CanTakePower(HEAL_POWER_COST_PER_SECOND) then
                fx:Show()
            else
                fx:Hide()
            end
        end)
    end
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--- building
    local function fn()
        local inst = CreateEntity()

        inst.entity:AddTransform()
        inst.entity:AddAnimState()
        inst.entity:AddSoundEmitter()
        inst.entity:AddNetwork()

        MakeObstaclePhysics(inst, 1)

        inst.AnimState:SetBank("loramia_building_guardian_creation")
        inst.AnimState:SetBuild("loramia_building_guardian_creation")
        inst.AnimState:PlayAnimation("idle",true)

        inst:AddTag("structure")
        inst:AddTag("loramia_building_guardian_creation")

        inst:AddTag("companion")

        inst.entity:SetPristine()
        ----------------------------------------------------------
        -- 电器节点系统
            device_com_install(inst)
        ----------------------------------------------------------
        --
            custom_workable_install(inst)
        ----------------------------------------------------------
        if not TheWorld.ismastersim then
            return inst
        end


        inst:AddComponent("inspectable")
        inst:AddComponent("lootdropper")
        ----------------------------------------------------------
        --- 战斗控制系统
            combat_install(inst)
        ----------------------------------------------------------
        --- 挖除
            workable_install(inst)
        ----------------------------------------------------------
        --- 积雪
            inst:WatchWorldState("issnowcovered", snow_init)
            snow_init(inst)
        ----------------------------------------------------------
        --- 
            CreateCoreLight(inst)
        ----------------------------------------------------------

        MakeHauntableLaunch(inst)

        return inst
    end
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- item
    local function item_fn()
        local inst = CreateEntity()

        inst.entity:AddTransform()
        inst.entity:AddAnimState()
        inst.entity:AddSoundEmitter()
        inst.entity:AddMiniMapEntity()
        inst.entity:AddNetwork()

        MakeInventoryPhysics(inst)
        MakeInventoryFloatable(inst, "med", 0.05, {0.85, 0.45, 0.85})

        inst.AnimState:SetBank("loramia_building_guardian_creation")
        inst.AnimState:SetBuild("loramia_building_guardian_creation")
        inst.AnimState:PlayAnimation("item")

        inst:AddTag("deploykititem")

        inst.entity:SetPristine()
        if not TheWorld.ismastersim then
            return inst
        end

        --------------------------------------------------------------------------
        ---
            inst:AddComponent("loramia_data")
        --------------------------------------------------------------------------
        ------ 物品名 和检查文本
            inst:AddComponent("inspectable")
            inst:AddComponent("inventoryitem")
            -- inst.components.inventoryitem:ChangeImageName("leafymeatburger")
            inst.components.inventoryitem.imagename = "loramia_building_guardian_creation_kit"
            inst.components.inventoryitem.atlasname = "images/inventoryimages/loramia_building_guardian_creation_kit.xml"
        -------------------------------------------------------------------
            MakeHauntableLaunch(inst)
        -------------------------------------------------------------------
        --- 落水影子
            local function shadow_init(inst)
                if inst:IsOnOcean(false) then       --- 如果在海里（不包括船）
                    -- inst.AnimState:Hide("SHADOW")
                    inst.AnimState:HideSymbol("shadow")
                else                                
                    -- inst.AnimState:Show("SHADOW")
                    inst.AnimState:ShowSymbol("shadow")
                end
            end
            inst:ListenForEvent("on_landed",shadow_init)
            shadow_init(inst)
        -------------------------------------------------------------------
        --- 积雪
            inst:WatchWorldState("issnowcovered", snow_init)
            snow_init(inst)
        -------------------------------------------------------------------
        --- 
            inst:AddComponent("stackable")
        -------------------------------------------------------------------
        --- 放置
            inst:AddComponent("deployable")
            inst.components.deployable.ondeploy = function(inst,pt,player)
                local ret_inst = SpawnPrefab("loramia_building_guardian_creation")
                inst.components.stackable:Get():Remove()
                ret_inst.Transform:SetPosition(pt.x,0,pt.z)
                inst:Remove()
            end
            inst.components.deployable:SetDeploySpacing(DEPLOYSPACING.NONE)
            inst.components.deployable.restrictedtag = "loramia"
        -------------------------------------------------------------------
        return inst
    end
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--- fx    
    local function fx_fn()
        local inst = CreateEntity()

        inst.entity:AddTransform()
        inst.entity:AddAnimState()    
        inst.entity:AddNetwork()

        inst.AnimState:SetBank("loramia_building_guardian_creation")
        inst.AnimState:SetBuild("loramia_building_guardian_creation")
        inst.AnimState:PlayAnimation("hit_fx",false)
        inst.AnimState:SetBloomEffectHandle("shaders/anim.ksh")

        inst:AddTag("CLASSIFIED")
        inst:AddTag("NOCLICK")
        inst:AddTag("INLIMBO")
        inst:AddTag("FX")
        inst:AddTag("NOCLICK")

        inst.entity:SetPristine()
        if not TheWorld.ismastersim then
            return inst
        end
        return inst
    end
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--- placer
    local function indecator_dispaly_for_stackable(inst)
        TheWorld:PushEvent("loramia_com_power_battery_indicator_active",inst)
        TheWorld:PushEvent("loramia_com_power_device_indicator_active",inst)
    end
    local function placer_postinit_fn(inst)
        indecator_dispaly_for_stackable(inst)
        inst:DoPeriodicTask(1,indecator_dispaly_for_stackable)
        local indicator = inst:SpawnChild("loramia_sfx_dotted_circle_client")
        indicator:PushEvent("Set",{
            radius = COMBAT_SEARCH_RADIUS,
        })
        indicator.AnimState:SetAddColour(0, 1, 0, 0)
        indicator.AnimState:SetMultColour(0, 1, 0, 1)
        indicator.AnimState:SetBloomEffectHandle("shaders/anim.ksh")

        snow_init(inst)

    end
----------------------------------------------------------------------------------------------------------------------

return Prefab("loramia_building_guardian_creation", fn, assets),
    Prefab("loramia_building_guardian_creation_fx", fx_fn, assets),
    Prefab("loramia_building_guardian_creation_kit", item_fn, assets),
    MakePlacer("loramia_building_guardian_creation_kit_placer", "loramia_building_guardian_creation", "loramia_building_guardian_creation", "idle", nil, nil, nil, nil, nil, nil, placer_postinit_fn)

